package top.yangguangmc.sunshine_anticheat.check.checks.player;

import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.entity.*;
import org.bukkit.event.EventHandler;
import org.bukkit.event.entity.EntityDamageByEntityEvent;
import org.bukkit.event.entity.ExplosionPrimeEvent;
import org.bukkit.util.Vector;
import top.yangguangmc.sunshine_anticheat.check.Check;
import top.yangguangmc.sunshine_anticheat.check.CheckCategory;
import top.yangguangmc.sunshine_anticheat.check.CheckSetting;
import top.yangguangmc.sunshine_anticheat.events.ServerTickEvent;
import top.yangguangmc.sunshine_anticheat.utils.Timer;
import top.yangguangmc.sunshine_anticheat.utils.Utils;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

public class AntiFireballCheck extends Check {
    private final Map<Player, Timer> beCheckedPlayers = new HashMap<>();
    private final Map<LargeFireball, Timer> fakeFireballs = new HashMap<>();
    private final Timer checkerTimer = new Timer();

    @CheckSetting(configName = "reset-interval")
    private int resetInterval = 15;

    public AntiFireballCheck() {
        super("AntiFireball", "anti-fireball", CheckCategory.PLAYER);
        checkerTimer.reset();
    }

    @EventHandler
    public void onEntityDamageByEntity(EntityDamageByEntityEvent event) {
        if (!validateCheckable(event.getDamager())) return;
        if (event.getEntityType() == EntityType.FIREBALL) {
            Player player = (Player) event.getDamager();
            if (player.getWorld().getPVP() && !player.hasPermission("sunshineac.bypass")) {   //只在此世界允许PVP时进行检查
                beCheckedPlayers.put(player, new Timer());
                LargeFireball fireball = (LargeFireball) event.getEntity();
                for (LargeFireball fakeBall : fakeFireballs.keySet()) {
                    if (fireball.getUniqueId().equals(fakeBall.getUniqueId())) {  //如果火球是一个bot
                        fireball.setVelocity(fireball.getVelocity().clone().zero());
                        fakeFireballs.remove(fireball);
                        fireball.remove();
                        failCheck(player, 1, "Attacked fireball bot behinds him.");
                        Timer playerTimer = beCheckedPlayers.get(player);
                        if (playerTimer != null) playerTimer.reset();
                        break;
                    }
                }
            }
        }
        if (event.getDamager() instanceof Fireball) {
            for (LargeFireball fakeFireball : fakeFireballs.keySet()) {
                if (event.getDamager().getUniqueId().equals(fakeFireball.getUniqueId()))
                    event.setCancelled(true);
            }
        }
    }

    @EventHandler
    public void onExplode(ExplosionPrimeEvent event) {
        if (!isEnabled()) return;
        if (event.getEntity() instanceof Fireball) {
            for (LargeFireball fakeFireball : fakeFireballs.keySet()) {
                if (event.getEntity().getUniqueId().equals(fakeFireball.getUniqueId()))
                    event.setCancelled(true);
            }
        }
    }

    @Override
    public void onPluginDisable() {
        for (LargeFireball fireball : fakeFireballs.keySet()) {
            fireball.setVelocity(fireball.getVelocity().clone().zero());
            fakeFireballs.remove(fireball);
            fireball.remove();
        }
        beCheckedPlayers.clear();
    }

    @EventHandler
    public void onTick(ServerTickEvent event) {
        if (!isEnabled()) return;
        for (LargeFireball fireball : fakeFireballs.keySet()) {
            Timer fireballTimer = fakeFireballs.get(fireball);
            if (fireballTimer.hasTimePassed(Utils.randomInt(500, 1000))) {
                fireballTimer.reset();
                fireball.setVelocity(fireball.getVelocity().clone().zero());
                fakeFireballs.remove(fireball);
                fireball.remove();
            }
        }
        for (Player player : beCheckedPlayers.keySet()) {
            Timer playerTimer = beCheckedPlayers.get(player);
            if (playerTimer.hasTimePassed(resetInterval * 1000L)) {
                playerTimer.reset();
                beCheckedPlayers.remove(player);
            }
        }
        if (checkerTimer.hasTimePassed(Utils.randomInt(2000, 5000))) {
            checkerTimer.reset();
            for (Player player : beCheckedPlayers.keySet()) {
                if (player == null) continue;
                World world = player.getWorld();
                Location location = player.getLocation().clone();
                location.setY(location.getY() + 1);
                location.subtract(location.getDirection().multiply(2.5));   //使其生成在玩家身后2.5格
                if (world.getBlockAt(location) == null || world.getBlockAt(location).getType() != Material.AIR)
                    continue;   //如果无法生成就算了
                LargeFireball fireball = (LargeFireball) world.spawnEntity(location, EntityType.FIREBALL);
                if (fireball == null) continue;
                List<Entity> entities = player.getWorld().getEntities().stream()
                        .filter(entity -> entity instanceof LivingEntity).collect(Collectors.toList());
                fireball.setShooter((LivingEntity) entities.get(Utils.randomInt(0, entities.size())));
                fireball.setDirection(new Vector(-0.005 + Utils.randomDouble(0, 0.01),
                        -Utils.randomDouble(0.005, 0.01), -0.005 + Utils.randomDouble(0, 0.01)));
//                fireball.setDirection(location.getDirection().add(new Vector(-0.005 + RandomUtil.randomDouble(0, 0.01),
//                        -RandomUtil.randomDouble(0.01, 0.03), -0.005 + RandomUtil.randomDouble(0, 0.01))));
                fakeFireballs.put(fireball, new Timer());
            }
        }
    }

}
